home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / misc / emu / QDOS2.lha / QLsource / ROMsrc / SER / SER_asm
Text File  |  1994-07-27  |  19KB  |  886 lines

  1.     SECTION    SER
  2.  
  3.     INCLUDE    '/INC/QDOS_inc'
  4.     INCLUDE    '/INC/AMIGA_inc'
  5.     INCLUDE    '/INC/AMIGQDOS_inc'
  6.  
  7. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. ; SER1_asm - serial device driver
  9. ;      - last modified 27/07/94
  10.  
  11. ; These are all the necessary serial port related sources,
  12. ; required to implement a QDOS serial device on the Amiga
  13. ; computer.
  14.  
  15. ; Amiga-QDOS sources by Rainer Kowallik
  16. ;  ...latest changes by Mark J Swift
  17.  
  18. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  19. ;  Define some constants.
  20.  
  21. B_4800    EQU    745
  22. B_9600    EQU    372
  23.  
  24. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25. ;  Define some extra serial variables
  26.  
  27. SER_MORE EQU    8        ; length of extra vars
  28.  
  29. SER_EOF    EQU    SER_END        ; EOF (CLOSE) protocol
  30. SER_TXD    EQU    SER_EOF+2    ; last transmitted character
  31. SER_RXD    EQU    SER_TXD+2    ; last received character
  32. SER_SHK    EQU    SER_RXD+2    ; status of DTR/RTS lines
  33.  
  34. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  35. ;  ROM header
  36.  
  37. BASE:
  38.     dc.l    $4AFB0001    ; ROM recognition code
  39.     dc.w    0
  40.     dc.w    ROM_START-BASE
  41.     dc.b    0,36,'Amiga-QDOS SER device driver v1.08 ',$A
  42.  
  43. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  44. ;  start of ROM code
  45.  
  46. ROM_START:
  47.     movem.l    d0-d2/a0-a3,-(a7)
  48.  
  49. ; --------------------------------------------------------------
  50. ;  allocate memory for variables
  51.  
  52.     move.l    #SV_LEN,d1
  53.     moveq    #MT.ALCHP,d0
  54.     moveq    #0,d2
  55.     trap    #1
  56.  
  57.     tst.l    d0
  58.     bne    ROM_EXIT
  59.  
  60. ; --------------------------------------------------------------
  61. ;  address of SER variables
  62.  
  63.     move.l    a0,AV.SERV
  64.     move.l    a0,a3        ; address of linkage block
  65.  
  66. ; --------------------------------------------------------------
  67. ;  enter supervisor mode and disable interrupts
  68.  
  69.     trap    #0
  70.  
  71.     ori.w    #$0700,sr    ; disable interrupts
  72.  
  73. ; --------------------------------------------------------------
  74. ;  link a custom routine into level 7 interrupt server
  75.  
  76.     lea    AV.LVL7link,a1
  77.     lea    SV.LVL7link(a3),a2
  78.  
  79.     move.l    (a1),(a2)
  80.     move.l    a2,(a1)
  81.  
  82.     lea    MY_LVL7(pc),a1
  83.     move.l    a1,$04(a2)
  84.  
  85. ; --------------------------------------------------------------
  86. ;  link a custom routine into Trap #1 exception
  87.  
  88.     lea    AV.TRP1link,a1
  89.     lea    SV.TRP1link(a3),a2
  90.  
  91.     move.l    (a1),(a2)
  92.     move.l    a2,(a1)
  93.  
  94.     lea    MY_TRP1(pc),a1
  95.     move.l    a1,$04(a2)
  96.  
  97. ; --------------------------------------------------------------
  98. ;  routines necessary for device driver
  99.  
  100.     lea    SER_IO(pc),a2    ; Input/Output routine
  101.     move.l    a2,SV_AIO(a3)
  102.  
  103.     lea    SER_OPEN(pc),a2    ; OPEN routine
  104.     move.l    a2,SV_AOPEN(a3)
  105.  
  106.     lea    SER_CLOSe(pc),a2    ; CLOSE routine
  107.     move.l    a2,SV_ACLOS(a3)
  108.  
  109. ; --------------------------------------------------------------
  110. ;  routines necessary for IO.SERIO. (used by SER I/O routine)
  111.  
  112.     lea    SER_TST(pc),a2    ; test for pending input
  113.     move.l    a2,SV.PEND(a3)
  114.  
  115.     lea    SER_FBYT(pc),a2    ; fetch byte
  116.     move.l    a2,SV.FBYTE(a3)
  117.  
  118.     lea    SER_SBYT(pc),a2    ; send byte
  119.     move.l    a2,SV.SBYTE(a3)
  120.  
  121.     move.w    #$4E75,SV.RTS(A3) ; RTS instruction at $34
  122.  
  123. ; --------------------------------------------------------------
  124. ;  set up hardware
  125.  
  126.     bsr.s    INIT_HW
  127.  
  128. ; --------------------------------------------------------------
  129. ;  link in device driver
  130.  
  131.     lea    SV_LIO(a3),a0    ; link address
  132.     moveq    #MT.LIOD,d0    ; link in IO device driver
  133.     trap    #1
  134.  
  135. ; -------------------------------------------------------------
  136. ; link in external interrupt to act on port free
  137.  
  138.     lea    XINT_SERv(pc),a2    ; address of routine
  139.     move.l    a2,SV_AXINT(a3)
  140.     lea    SV_LXINT(a3),a0
  141.     moveq    #MT.LXINT,d0
  142.     trap    #1
  143.  
  144. ; -------------------------------------------------------------
  145. ; link in poll interrupt to re-enable serial send / receive
  146.  
  147.     lea    POLL_SERv(pc),a2    ; address of routine
  148.     move.l    a2,SV_APOLL(a3)
  149.     lea    SV_LPOLL(a3),a0
  150.     moveq    #MT.LPOLL,d0
  151.     trap    #1
  152.  
  153. ; --------------------------------------------------------------
  154. ;  enable interrupts and re-enter user mode
  155.  
  156.     andi.w    #$D8FF,sr
  157.  
  158. ; --------------------------------------------------------------
  159. ROM_EXIT:
  160.     movem.l    (a7)+,d0-d2/a0-a3
  161.  
  162.     rts
  163.  
  164. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  165. ;  set up hardware
  166.  
  167. INIT_HW:
  168.     move.l    d7,-(a7)
  169.  
  170.     MOVE.B    #%11000000,CIAB_PRA ; DTR low (1) not ready to receive
  171.                   ; RTS low (1) nothing to send
  172.  
  173.     MOVE.W    #B_9600,D0
  174.     BSET    #15,D0        ; 9 bit receive data
  175.     MOVE.W    D0,SERPER    ; Set baudrate
  176.  
  177.     move.w    #%0000100000000001,INTREQ ; clear interrupts
  178.     move.w    #%1000100000000001,INTENA ; enable RBF & TBE
  179.                         ; interrupts
  180.     move.l    (a7)+,d7
  181.     rts
  182.  
  183. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  184. ;  Serial open routine
  185.  
  186. SER_OPEN:
  187.     suba.w    #10,a7        ; room for 5 words on
  188.     MOVEA.L    A7,A3        ; stack.
  189.  
  190.     move.w    IO.NAME,a4    ; decode device name
  191.     jsr    (a4)
  192.  
  193.     BRA.S    SER_O_X        ; error
  194.     BRA.S    SER_O_X        ; error
  195.     BRA.S    SER_O_CHK    ; OK, check values
  196.  
  197.     DC.B    0,3,'SER',0
  198.     dc.w    5        ; 5 parameters
  199.  
  200.     dc.w    -1        ; word, no seperator
  201.     dc.w    1        ; default port
  202.  
  203.     dc.w    4        ; char value, 4 options
  204.     DC.B    'OEMS'        ; Parity
  205.  
  206.     DC.W    2        ; char value, 2 options
  207.     DC.B    'IH'        ; handshake
  208.  
  209.     dc.w    4        ; char value, 4 options
  210.     dc.b    'RNCL'        ; eol protocol
  211.  
  212.     dc.w    2        ; char value, 2 options
  213.     dc.b    'FZ'        ; eof protocol
  214.  
  215. ; --------------------------------------------------------------
  216. SER_O_NF:
  217.     moveq    #ERR.NF,d0    ; not found
  218.     bra    SER_O_X
  219.  
  220. ; --------------------------------------------------------------
  221. SER_O_IU:
  222.     moveq    #ERR.IU,d0    ; in use
  223.  
  224. ; --------------------------------------------------------------
  225. SER_O_X:
  226.     adda.w    #10,a7
  227.     ANDI.W    #$F8FF,SR
  228.     RTS
  229.  
  230. ; --------------------------------------------------------------
  231. SER_O_CHK:
  232.     ORI.W    #$0700,SR    ; disable interrupts
  233.  
  234.     MOVE.W    (A7),D4        ; get port
  235.     ble.s    SER_O_NF     ; <=0, bad value
  236.  
  237.     SUBQ.W    #2,D4
  238.     bgt.s    SER_O_NF     ; >2, bad value
  239.  
  240.     lea    SV_SER1C(a6),a5    ; Receive queue, channel 1
  241.     move.l    (a5),d0        ; address set?
  242.     BEQ.S    L00B56        ; no queue, no chan def blk
  243.  
  244.     movea.l    d0,a0
  245.     suba.w    #SER_RXQ,a0    ; addrs of old chan def blk
  246.     bclr    #7,SER_TXQ(a0)    ; output queue empty?
  247.     BNE.S    L00B6A        ; yes, so continue
  248.     bra.s    SER_O_IU     ; no, so exit with error
  249.  
  250. L00B56:
  251.     move.w    #(SER_END+SER_MORE),d1 ; allocate chan def block
  252.     move.w    MM.ALCHP,a4    ; for first time
  253.     JSR    (A4)
  254.     bne.s    SER_O_X        ; exit if error occured
  255.  
  256.     moveq    #SER_TXQL,d1    ; length of transmit queue
  257.     lea    SER_TXQ(a0),a2    ; address of transmit queue
  258.     move.w    IO.QSET,a4    ; set up queue (not used
  259.     jsr    (a4)        ; before
  260.  
  261. L00B6A:
  262.     moveq    #SER_RXQL,d1    ; length of receive queue
  263.     lea    SER_RXQ(a0),a2    ; address of receive queue
  264.     move.w    IO.QSET,a4    ; set up queue
  265.     jsr    (a4)
  266.  
  267.     move.l    a2,SV_SER1C(a6)    ; Receive queue, channel 1
  268.  
  269.     move.l    (a7),SER_CHNO(a0) ; store port number, parity
  270.     move.l    4(a7),SER_TXHS(a0) ; store handshake, protocol
  271.     move.w    8(a7),SER_EOF(a0) ; store EOF protocol
  272.  
  273.     subq.w    #1,SER_TXHS(a0)    ; <=0 ignore, 1 handshake
  274.     subq.w    #2,SER_PROT(a0)    ; <0 raw : 0 CR/LF : 1 CR : 2 LF
  275.     subq.w    #1,SER_EOF(a0)    ; <0 none : 0 FF : CTRL-Z
  276.  
  277. ; --------------------------------------------------------------
  278. ;  set up hardware
  279.  
  280.     move.b    #%01000000,CIAB_PRA ; DTR high (0) ready to receive
  281.                   ; CTS low (1) nothing to send
  282.     move.b    #%01000000,SER_SHK(a0) ; mirror DTR/CTS values
  283.  
  284. ; --------------------------------------------------------------
  285. SER_O_OK:
  286.     moveq    #ERR.OK,d0    ; signal "no error"
  287.     bra    SER_O_X
  288.  
  289. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  290. ;  serial close routine
  291.  
  292. SER_CLOSe:
  293.     tst.b    1+SER_EOF(a0)
  294.     blt.s    SER_C2        ; cont if no eof protocol
  295.  
  296.     beq.s    SER_C1        ; branch if FF protocol
  297.  
  298.     move.w    #26,d1        ; else send CTRL-Z
  299.     bra.s    SER_CLUP
  300.  
  301. SER_C1:
  302.     move.w    #12,d1        ; send Form Feed
  303.  
  304. SER_CLUP:
  305.     bsr    SER_SBOK
  306.     cmp.w    #ERR.NC,d0
  307.     beq.s    SER_CLUP
  308.  
  309. SER_C2:
  310.     MOVE.B    #%11000000,CIAB_PRA ; DTR low (1) not ready to receive
  311.                   ; RTS low (1) nothing to send
  312.  
  313.     lea    SER_TXQ(a0),a2
  314.     move.w    IO.QEOF,a4    ; put EOF marker in queue
  315.     jsr    (a4)
  316.  
  317.     moveq    #ERR.OK,d0    ; signal "no errors"
  318.     RTS
  319.  
  320. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  321. ;  Serial - input / output routine
  322.  
  323. SER_IO:
  324.     pea    SV.PEND(a3)    ; pretend call just before
  325.     move.w    IO.SERIO,a4
  326.     JMP    (A4)
  327.  
  328. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  329. ;  Serial - test for pending input
  330.  
  331. SER_TST:
  332.     lea    SER_RXQ(a0),a2   ; pointer to buffer
  333.     move.w    IO.QTEST,a4
  334.     jmp    (a4)
  335.  
  336. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  337. ;  Serial - Send byte d1
  338.  
  339. SER_SBYT:
  340.     lea    SER_TXQ(a0),a2
  341.  
  342.     move.l    d1,d3
  343.     move.w    IO.QTEST,a4
  344.     jsr    (a4)
  345.     move.l    d3,d1
  346.  
  347.     cmpi.w    #ERR.EF,d0
  348.     beq.s    SER_SB4
  349.  
  350.     moveq    #ERR.OK,d0
  351.  
  352.     cmpi.w    #$6,d2
  353.     bge.s    SER_SB5
  354.  
  355.     moveq    #ERR.NC,d0
  356.  
  357. SER_SB4:
  358.     rts
  359.  
  360. SER_SB5:
  361.     move.b    1+SER_TXD(a0),d3    ; remember old TX code
  362.     move.b    d1,1+SER_TXD(a0)    ; save new TX code
  363.  
  364.     tst.b    1+SER_PROT(a0)
  365.     blt.s    SER_SBOK     ; branch if no eol protocol
  366.  
  367.     cmpi.b    #$0A,d1        ; Line Feed?
  368.     beq.s    SER_SB1
  369.  
  370.     cmpi.b    #$0D,d1        ; Carriage Return?
  371.     bne.s    SER_SBOK     ; branch if neither
  372.  
  373. SER_SB1:
  374.     cmpi.b    #$0A,d3        ; Line Feed?
  375.     beq.s    SER_SB2
  376.  
  377.     cmpi.b    #$0D,d3        ; Carriage Return?
  378.     bne.s    SER_SB3
  379.  
  380. SER_SB2:
  381.     cmp.b    d1,d3
  382.     beq.s    SER_SB3
  383.  
  384.     move.b    #$FF,1+SER_TXD(a0) ; ignore LF in CR/LF couple
  385.     moveq    #ERR.OK,d0
  386.     rts
  387.  
  388. SER_SB3:
  389.     tst.b    1+SER_PROT(a0)
  390.     beq.s    SER_SB6        ; branch if CR/LF protocol
  391.  
  392.     cmp.b    #2,1+SER_PROT(a0)
  393.     beq.s    SER_SB7        ; branch if LF
  394.  
  395.     moveq    #$0D,d1        ; else use CR
  396.     bra.s    SER_SBOK
  397.  
  398. SER_SB6:
  399.     moveq    #$0D,d1
  400.     bsr    SER_SBOK
  401.  
  402. SER_SB7:
  403.     moveq    #$0A,d1
  404.  
  405. SER_SBOK:
  406.     tst.b    SV_TRAN(a6)    ; key translation present ?
  407.     beq.s    L00BDE        ; if not -> L00BDE
  408.  
  409. SER_SBOK1:
  410.     BSR    TRAKEY_S
  411.  
  412.     rts
  413.  
  414. L00BDE:
  415.     move.w    SER_PAR(a0),d0
  416.     MOVE.B    L00BEA(PC,D0.W),D0
  417.     JMP    L00BEA(PC,D0.W)
  418. L00BEA:
  419.     DC.B    WNOPAR-L00BEA
  420.     DC.B    WODD-L00BEA
  421.     DC.B    WEVEN-L00BEA
  422.     DC.B    WBIT7-L00BEA
  423.     DC.B    WBIT8-L00BEA
  424.     DC.B    0
  425.  
  426. ; --------------------------------------------------------------
  427. WBIT7:
  428.     BSET    #7,D1
  429.  
  430. ; --------------------------------------------------------------
  431. WNOPAR:
  432.     lea    SER_TXQ(a0),a2
  433.  
  434.     move.w    IO.QIN,a4    ; put byte d1 into queue a2
  435.     jsr    (a4)
  436.     BRA    L00C74
  437.  
  438. ; --------------------------------------------------------------
  439. WBIT8:
  440.     BCLR    #7,D1
  441.     BRA.S    WNOPAR
  442.  
  443. ; --------------------------------------------------------------
  444. WODD:
  445.     BSR    L00C76
  446.     BCHG    #7,D1
  447.     BRA.S    WNOPAR
  448.  
  449. ; --------------------------------------------------------------
  450. WEVEN:
  451.     BSR    L00C76
  452.     BRA.S    WNOPAR
  453.  
  454. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  455. ;  Serial - fetch byte
  456.  
  457. SER_FBYT:
  458.     move.l    SV_SER1C(a6),a2          ; Pointer to buffer
  459.  
  460.     move.w    IO.QOUT,a4
  461.     jsr    (a4)
  462.  
  463.     BNE    L00C74
  464.  
  465. SER_RDAT:
  466.     MOVE.W    $1A(A0),D3
  467.     MOVE.B    L00C3A(PC,D3.W),D3
  468.     JMP    L00C3A(PC,D3.W)
  469.  
  470. L00C3A:
  471.     DC.B    RNOPAR-L00C3A
  472.     DC.B    RIMPAR-L00C3A
  473.     DC.B    RPAR-L00C3A
  474.     DC.B    RBIT71-L00C3A
  475.     DC.B    RBIT70-L00C3A
  476.     DC.B    0
  477.  
  478. ; --------------------------------------------------------------
  479. RBIT71:
  480.     BCHG    #7,D1
  481.     BRA.S    RBIT70
  482.  
  483. ; --------------------------------------------------------------
  484. RIMPAR:
  485.     BCHG    #7,D1
  486.  
  487. ; --------------------------------------------------------------
  488. RPAR:
  489.     BSR.S    L00C76
  490.  
  491. ; --------------------------------------------------------------
  492. RBIT70:
  493.     BTST    #7,D1
  494.     BEQ.S    RNOPAR
  495.     MOVEQ    #-13,D0        ; XMIT error
  496.  
  497. ; --------------------------------------------------------------
  498. RNOPAR:
  499.     tst.b    SV_TRAN(a6)    ; Key translation present ?
  500.     BEQ.S    L00C66
  501.     BSR    TRAKEY_R
  502.  
  503. L00C66:
  504.     move.b    1+SER_RXD(a0),d3    ; remember old RX code
  505.     move.b    d1,1+SER_RXD(a0)    ; save new RX code
  506.  
  507.     tst.b    1+SER_PROT(a0)
  508.     blt.s    L00C74        ; branch if no EOL protocol
  509.  
  510.     cmpi.b    #$0A,d1        ; Line Feed?
  511.     beq.s    RNOP1
  512.  
  513.     cmpi.b    #$0D,d1        ; Carriage Return?
  514.     bne.s    L00C74        ; branch if neither
  515.  
  516. RNOP1:
  517.     cmpi.b    #$0A,d3        ; Line Feed?
  518.     beq.s    RNOP2
  519.  
  520.     cmpi.b    #$0D,d3        ; Carriage Return?
  521.     bne.s    RNOP3
  522.  
  523. RNOP2:
  524.     cmp.b    d1,d3
  525.     beq.s    RNOP3
  526.  
  527.     move.b    #$FF,1+SER_RXD(a0) ; ignore LF in CR/LF couple
  528.     moveq    #ERR.NC,d0
  529.     rts
  530.  
  531. RNOP3:
  532.     moveq    #$0A,d1        ; change to LF
  533.  
  534. L00C74:
  535.     RTS
  536.  
  537. ; --------------------------------------------------------------
  538. L00C76:
  539.     MOVEQ    #6,D3
  540.     MOVE.B    D1,D4
  541.  
  542. L00C7A:
  543.     ROR.B    #1,D1
  544.     EOR.B    D1,D4
  545.     DBF    D3,L00C7A
  546.     ROXL.B    #1,D4
  547.     ROXR.B    #1,D1
  548.     RTS
  549.  
  550. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  551. ;  Translate key d1 for sending
  552.  
  553. TRAKEY_S:
  554.     MOVEM.L    D1-D3/A1,-(A7)
  555.     MOVEQ    #0,D0
  556.     movea.l    SV_TRTAB(a6),a1    ; Pointer to key translation
  557.     MOVE.W    2(A1),D2
  558.     LEA    0(A1,D2.W),A1
  559.     TST.B    D1
  560.     BEQ.S    L0B5D6
  561.     MOVE.B    0(A1,D1.W),D0
  562.     TST.B    D0
  563.     BEQ.S    L0B58E
  564.     MOVE.B    D0,D1
  565.     BRA.S    L0B5D6
  566.  
  567. L0B58E:
  568.     MOVE.L    D1,D3
  569.  
  570.     move.w    IO.QTEST,a4
  571.     jsr    (a4)
  572.  
  573.     MOVE.L    D3,D1
  574.     CMPI.W    #$FFF6,D0
  575.     BEQ.S    L0B5DC
  576.     MOVEQ    #0,D0
  577.     CMPI.W    #$0003,D2
  578.     BGE.S    L0B5AA
  579.     MOVEQ    #-1,D0
  580.     BRA.S    L0B5DC
  581.  
  582. L0B5AA:
  583.     MOVEA.L    SV_TRTAB(A6),A1    ; pointer to key translation
  584.     MOVE.W    4(A1),D2     ; Start of system messages
  585.     LEA    0(A1,D2.W),A1
  586.     MOVE.B    (A1)+,D3
  587.  
  588. L0B5B8:
  589.     BEQ.S    L0B5DC
  590.     CMP.B    (A1)+,D1
  591.     BEQ.S    L0B5C4
  592.     ADDQ.L    #3,A1
  593.     SUBQ.B    #1,D3
  594.     BRA.S    L0B5B8
  595.  
  596. L0B5C4:
  597.     MOVE.B    (A1)+,D1
  598.     bsr    L00BDE        ; put byte d1 into queue a2
  599.     MOVE.B    (A1)+,D1
  600.     bsr    L00BDE        ; put byte d1 into queue a2
  601.     MOVE.B    (A1),D1
  602.  
  603. L0B5D6:
  604.     bsr    L00BDE        ; put byte d1 into queue a2
  605.  
  606. L0B5DC:
  607.     MOVEM.L    (A7)+,D1-D3/A1
  608.     RTS
  609.  
  610. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  611. ;  translate key d1 for reading
  612.  
  613. TRAKEY_R:
  614.     MOVEM.L    D0/D2/A1,-(A7)    ; D0-D2/A1 as before can not
  615.                 ; work correctly
  616.     MOVEA.L    $146(A6),A1    ; pointer to key translation
  617.     MOVE.W    2(A1),D2
  618.     LEA    0(A1,D2.W),A1
  619.     MOVE.B    0(A1,D1.W),D0
  620.     TST.B    D0
  621.     BEQ.S    L0B60E
  622.     MOVE.W    D1,D2
  623.  
  624. L0B5FC:
  625.     MOVE.B    0(A1,D2.W),D0
  626.     CMP.B    D0,D1
  627.     BEQ.S    L0B60C
  628.     ADDQ.B    #1,D2
  629.     CMP.B    D2,D1
  630.     BNE.S    L0B5FC
  631.     BRA.S    L0B60E
  632.  
  633. L0B60C:
  634.     MOVE.B    D2,D1
  635.  
  636. L0B60E:
  637.     MOVEM.L    (A7)+,D0/D2/A1    ; D0-D2/A1 as before can not
  638.                 ; work correctly
  639.     RTS
  640.  
  641. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  642. ;  poll interrupt server for serial port. If interrupts are off,
  643. ;  restarts interrupts by sending a byte.
  644.  
  645. POLL_SERv:
  646.     bsr    SER_SEND     ; if transmit buffer is
  647.                 ; empty, and CTS bit is
  648.                 ; clear, then send a byte
  649.  
  650.     bsr    SER_RECV     ; if there's room in input
  651.                 ; buffer, fetch byte.
  652. POLL_X:
  653.     rts
  654.  
  655. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  656. ;  external interrupt server for serial port
  657.  
  658. XINT_SERv:
  659.     movem.l    d7/a0,-(a7)
  660.  
  661.     move.w    INTENAR,d7    ; read interrupt enable reg
  662.     btst    #0,d7        ; branch if ints not on
  663.     beq    XINT_1
  664.  
  665.     move.w    INTREQR,d7    ; read interrupt request reg
  666.     btst    #0,d7        ; branch if from output
  667.     bne    TBE_XINT     ; buffer empty
  668.     bra    XINT_OTHer
  669.  
  670. XINT_1:
  671.     btst    #11,d7        ; branch if ints not on
  672.     beq    XINT_OTHer
  673.  
  674.     move.w    INTREQR,d7    ; read interrupt request reg
  675.     btst    #11,d7        ; branch if from input
  676.     bne    RBF_XINT     ; buffer full
  677.  
  678. ; --------------------------------------------------------------
  679. ;  otherwise let another external interrupt server handle it
  680.  
  681. XINT_OTHer:
  682.     movem.l    (a7)+,d7/a0
  683.     rts
  684.  
  685. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  686. ;  RBF Interrupt. Reads a byte into the queue when serial data
  687. ;  is ready (read buffer is full).
  688.  
  689. RBF_XINT:
  690.     bsr    SER_RECV     ; send next byte
  691.  
  692.     move.w    #%0000100000000000,INTREQ ; reset RBF int.
  693.  
  694. RBF_XINT_X:
  695.     bra.s    XINT_EXIt
  696.  
  697. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  698. ;  TBE Interrupt. Tries to send another byte from queue when
  699. ;  transmit buffer becomes empty.
  700.  
  701. TBE_XINT:
  702.     move.w    #%0000000000000001,INTREQ ; reset TBE int.
  703.  
  704.     bsr    SER_SEND     ; send next byte
  705.  
  706. TBE_XINT_X:
  707.  
  708. ; -------------------------------------------------------------
  709. XINT_EXIt:
  710.     bra.s    XINT_OTHer
  711.  
  712. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  713. SER_RECV:
  714.     movem.l    d0-d3/a0-a4,-(a7)
  715.  
  716.     MOVE.L    SV_SER1C(a6),a2    ; Receive queue channel 1
  717.     MOVE.L    A2,D0        ; channel open ?
  718.     BEQ.S    SER_RECVX    ; no, ignore data.
  719.  
  720.     move.b    1+SER_TXHS-SER_RXQ(a2),d1
  721.     ble.s    SER_RECV1    ; branch if no handshake
  722.  
  723.     move.b    SER_SHK-SER_RXQ(a2),d1
  724.     ori.b    #%10000000,d1
  725.     move.b    d1,SER_SHK-SER_RXQ(a2)
  726.     MOVE.B    d1,CIAB_PRA    ; DTR low (1) - can't receive
  727.  
  728. SER_RECV1:
  729.     btst    #(14-8),SERDATR    ; receive buffer full?
  730.     beq.s    SER_RECV2    ; no, enable transmission
  731.  
  732.     MOVE.W    SERDATR,D1    ; get data
  733.  
  734.     move.w    #%0000100000000000,INTREQ ; reset RBF int.
  735.  
  736.     move.w    IO.QIN,a4
  737.     jsr    (a4)        ; put byte d1 into queue a2
  738.     TST.W    D0        ; any errors ?
  739.     BEQ.S    SER_RECV1    ; no, check if another
  740.  
  741.     bra.s    SER_RECVX    ; yes, stop transmission
  742.  
  743. SER_RECV2:
  744.     move.w    IO.QTEST,a4
  745.     jsr    (a4)        ; check free space in queue
  746.  
  747.     CMP.W    #10,D2        ; receiv queue nearly full?
  748.     BCS.S    SER_RECVX    ; yes, stop reception
  749.  
  750.     move.b    SER_SHK-SER_RXQ(a2),d1
  751.     and.b    #%01111111,d1
  752.     move.b    d1,SER_SHK-SER_RXQ(a2)
  753.     MOVE.B    d1,CIAB_PRA    ; DTR high (0)- enable reception
  754.  
  755. SER_RECVX:
  756.     movem.l    (a7)+,d0-d3/a0-a4
  757.     rts
  758.  
  759. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  760. ;  write next byte from queue to serial port
  761.  
  762. SER_SEND:
  763.     movem.l    d0-d1/d7/a2-a4,-(a7)
  764.  
  765.     move.l    SV_SER1C(a6),d1    ; address of receive Q
  766.     beq.s    SER_S_X        ; exit if Q doesn't exist
  767.  
  768.     move.w    #(SER_TXQ-SER_RXQ),a2
  769.     adda.l    d1,a2        ; address of transmit Q
  770.  
  771.     move.b    1+SER_TXHS-SER_TXQ(a2),d1
  772.     ble.s    SER_S1
  773.  
  774.     btst    #4,CIAB_PRA    ; test CTS bit
  775.     bne.s    SER_S_X        ; exit if not ready
  776.  
  777. SER_S1:
  778.     btst    #(13-8),SERDATR    ; transmit buffer empty?
  779.     BEQ.S    SER_S_X
  780.  
  781.     moveq    #0,d1
  782.     move.w    IO.QOUT,a4
  783.     jsr    (a4)        ; get byte d1 from queue a2
  784.     tst.l    d0
  785.     beq.s    SER_S_DO      ; send it if no error
  786.  
  787.     move.b    SER_SHK-SER_TXQ(a2),d0 ; otherwise...
  788.     ori.b    #%01000000,d0
  789.     move.b    d0,SER_SHK-SER_TXQ(a2)
  790.     MOVE.B    d0,CIAB_PRA    ; RTS low (1) - nothing to send
  791.  
  792.     bra.s    SER_S_X        ; and exit
  793.  
  794. SER_S_DO:
  795.     move.b    SER_SHK-SER_TXQ(a2),d0
  796.     andi.b    #%10111111,d0
  797.     move.b    d0,SER_SHK-SER_TXQ(a2)
  798.     MOVE.B    d0,CIAB_PRA    ; RTS high (0) - ready to send
  799.  
  800.     or.w    #$300,d1     ; set two stop bits
  801.     move.w    #%0000000000000001,INTREQ ; reset TBE int.
  802.     move.w    D1,SERDAT    ; write data to serial port
  803.  
  804. SER_S_X:
  805.     movem.l    (a7)+,d0-d1/d7/a2-a4
  806.     RTS
  807.  
  808. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  809. ;  Custom LVL7 routine to initialise hardware
  810.  
  811. MY_LVL7:
  812.     bsr    INIT_HW
  813.  
  814.     subq.l    #4,a7
  815.     movem.l    a3,-(a7)
  816.     move.l    AV.SERV,a3
  817.     move.l    SV.LVL7link(a3),a3
  818.     move.l    4(a3),4(a7)    ; address of next routine
  819.     movem.l    (a7)+,a3
  820.  
  821.     rts
  822.  
  823. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  824. ;  A patch to replace TRAP#1 calls to: MT_BAUD (d0=$12)
  825.  
  826. MY_TRP1:
  827.     bsr    INI_A5A6
  828.  
  829.     cmp.b    #$12,d0
  830.     beq    MT_BAUD
  831.  
  832.     movem.l    (a7)+,d7/a5/a6    ; restore registers
  833.  
  834.     subq.l    #4,a7
  835.     movem.l    a3,-(a7)
  836.     move.l    AV.SERV,a3
  837.     move.l    SV.TRP1link(a3),a3
  838.     move.l    4(a3),4(a7)    ; address of next routine
  839.     movem.l    (a7)+,a3
  840.  
  841.     rts
  842.  
  843. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  844. ; initialise A5 and A6 prior to performing a TRAP routine
  845.  
  846. INI_A5A6
  847.     SUBQ.L    #8,A7
  848.     MOVE.L    8(A7),-(A7)
  849.     MOVEM.L    D7/A5/A6,4(A7)
  850.  
  851.     move.l    a7,d7
  852.     andi.l    #$FFFF8000,d7
  853.     move.l    d7,a6        ; Calc address of sys vars
  854.  
  855.     LEA    4(A7),A5     ; A5 points to saved
  856.                 ; Registers D7,A5,A6
  857.     MOVEQ    #$7F,D7
  858.     AND.L    D7,D0
  859.     RTS
  860.  
  861. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  862. ;  TRAP #1 with D0=$12
  863. ;  set baud rate
  864.  
  865. MT_BAUD:
  866.     MOVEM.L    D2/D6/A0-A2,-(A7)
  867.     MOVE.L    D1,D0        ; D0=baudrate
  868.     MOVE.L    #3579546,D1    ; D1=1/2.79365E-7
  869.     DIVU    D0,D1        ; D1=D1/baudrate
  870.     AND.L    #$FFFF,D1    ; mask out remainder
  871.     SUBQ.W    #1,D1        ; to be exact
  872. ;    ORI.W   #$8000           ; we may receive two stop bits
  873.     move.w    d1,SERPER    ; write to SERPER
  874.     MOVEM.L    (A7)+,D2/D6/A0-A2
  875.  
  876.     moveq    #0,d0
  877.  
  878. ; --------------------------------------------------------------
  879. ;  exit from TRAP call
  880.  
  881. TRAP1_X    movem.l    (a7)+,d7/a5/a6    ; exit from exception
  882.     rte
  883.  
  884. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  885.     END
  886.